package cn.arnold.juc;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author Arnold-Xiang
 * @Info 两个线程轮流输出
 * t1输出：1,2,3,4,5,6
 * t2输出：A,B,C,D,E,F
 * 输出：1A2B3C4D5E6F
 */
public class TwoThreadByTurnOut {
    public static void main(String[] args) {
        //lockSupport();
        //syn();
        lock();
    }

    /**
     * LockSupport：park---unpark
     */
    static Thread t1 = null;
    static Thread t2 = null;

    public static void lockSupport() {
        char[] chN = "123456".toCharArray();
        char[] chW = "ABCDEF".toCharArray();

        t1 = new Thread(() -> {
            for (char c : chN) {
                System.out.println(c);
                LockSupport.unpark(t2); //唤醒t2
                LockSupport.park(); // 自己（t1）阻塞
            }
        }, "t1");

        t2 = new Thread(() -> {
            for (char c : chW) {
                LockSupport.park(); // 自己(t2)阻塞
                System.out.println(c);
                LockSupport.unpark(t1); //唤醒t1
            }
        }, "t1");

        t1.start();
        t2.start();
    }

    /**
     * Synchronized：wait---notify
     */
    public static void syn() {
        char[] chN = "123456".toCharArray();
        char[] chW = "ABCDEF".toCharArray();
        Object o = new Object();    //对象锁
        new Thread(() -> {
            synchronized (o) {
                for (char c : chN) {
                    System.out.println(c);
                    try {
                        o.notify();
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                o.notify();
            }
        }, "t1").start();

        new Thread(() -> {
            synchronized (o) {
                for (char c : chW) {
                    System.out.println(c);
                    try {
                        o.notify();
                        o.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                o.notify();
            }
        }, "2").start();
    }

    /**
     * ReentrantLock：await---signal
     * CountDownLaunch保证t1线程先执行：t1-countDown(),t2-await()
     */
    public static void lock() {
        char[] chN = "123456".toCharArray();
        char[] chW = "ABCDEF".toCharArray();
        Lock lock = new ReentrantLock();
        Condition c1 = lock.newCondition();
        Condition c2 = lock.newCondition();
        CountDownLatch ctl = new CountDownLatch(1);
        new Thread(() -> {
            lock.lock();
            try {
                for (char c : chN) {
                    System.out.println(c);
                    ctl.countDown();
                    c2.signal();
                    c1.await();
                }
                c2.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "t1").start();

        new Thread(() -> {
            // 等待t1运行后t2再输出
            try {
                ctl.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.lock();
            try {
                for (char c : chW) {
                    System.out.println(c);
                    c1.signal();
                    c2.await();
                }
                c1.signal();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "t2").start();
    }
}
